package com.changhong;

/**
 * Created by Administrator on 2018/10/13
 */
public class Test {

    public static void main(String[] args) {
        int[] data = genData(10);
        print(data);
//        System.out.println("start");
//        sortBubble(data);
//        sortSelection(data);
//        sortInsert(data);
//        sortMerge(data);
//        int[] arr = {5, 9, 7, 1, 8, 4, 3, 2, 6};
        sortHeap(data);
//        System.out.println("end");
        sortQuick(data);
        print(data);
    }

    private static void sortQuick(int[] data) {
        sortQuick(data, 0, data.length - 1);
    }

    private static void sortQuick(int[] data, int left, int right) {
        if (left >= right) {
            return;
        }

        int position = partition(data, left, right);
        sortQuick(data, left, position);
        sortQuick(data, position + 1, right);
    }

    private static int partition(int[] data, int left, int right) {
        int position = left;
        int value = data[left];

        for (int index = left + 1; index <= right; index++) {
            if (data[index] < value) {
                position++;
                swap(data, position, index);
            }
        }

        swap(data, left, position);

        return position;
    }

    public static void sortBubble(int[] data) {
        for (int i = 0; i < data.length; i++) {
            for (int j = 0; j < data.length - 1 - i; j++) {
                if (data[j] > data[j + 1])
                    swap(data, j, j + 1);
                print(data);
            }
        }
    }

    public static void sortSelection(int[] data) {
        for (int i = 0; i < data.length; i++) {
            int minIndex = i;
            for (int j = i + 1; j < data.length; j++) {
                if (data[j] < data[minIndex])
                    minIndex = j;
            }
            if (minIndex > i) swap(data, i, minIndex);
            print(data);
        }
    }

    public static void sortInsert(int[] data) {
        for (int i = 0; i < data.length; i++) {
            if (i == data.length - 1) break;
            for (int j = i + 1; j > 0; j--) {
                if (data[j] < data[j - 1])
                    swap(data, j - 1, j);
            }
            print(data);
        }
    }

    public static void sortMerge(int[] data) {
        int temp[] = new int[data.length];
        sortMerge(data, 0, data.length - 1, temp);
    }

    public static void sortMerge(int[] data, int left, int right, int[] temp) {
        System.out.println("[" + left + "," + right + "]");
        if (left < right) {
            int mid = left + (right - left) / 2;
            sortMerge(data, left, mid, temp);
            sortMerge(data, mid + 1, right, temp);
//            System.out.println(left + " " + mid + " " + right);
            merge(data, left, mid, right, temp);
//            print(data);
        }
    }

    private static void merge(int[] data, int left, int mid, int right, int[] temp) {
        int i = left;
        int j = mid + 1;
        int t = 0;
        while (i <= mid && j <= right) {
            if (data[i] <= data[j]) {
                temp[t++] = data[i++];
            } else {
                temp[t++] = data[j++];
            }
        }
        while (i <= mid) {
            temp[t++] = data[i++];
        }
        while (j <= right) {
            temp[t++] = data[j++];
        }
        t = 0;
        while (left <= right) {
            data[left++] = temp[t++];
        }
    }

    public static void sortHeap(int[] arr) {
        //1.构建大顶堆
        for (int i = arr.length / 2 - 1; i >= 0; i--) {
            //从第一个非叶子结点从下至上，从右至左调整结构
            adjustHeap(arr, i, arr.length);
        }
        //2.调整堆结构+交换堆顶元素与末尾元素
        for (int j = arr.length - 1; j > 0; j--) {
            swap(arr, 0, j);//将堆顶元素与末尾元素进行交换
            adjustHeap(arr, 0, j);//重新对堆进行调整
        }

    }

    /**
     * 调整大顶堆（仅是调整过程，建立在大顶堆已构建的基础上）
     *
     * @param arr
     * @param i
     * @param length
     */
    public static void adjustHeap(int[] arr, int i, int length) {
         int temp = arr[i];//先取出当前元素i
        for (int k = i * 2 + 1; k < length; k = k * 2 + 1) {//从i结点的左子结点开始，也就是2i+1处开始
            if (k + 1 < length && arr[k] < arr[k + 1]) {//如果左子结点小于右子结点，k指向右子结点
                k++;
            }
            if (arr[k] > temp) {//如果子节点大于父节点，将子节点值赋给父节点（不用进行交换）
                arr[i] = arr[k];
                i = k;
            } else {
                break;
            }
        }
        arr[i] = temp;//将temp值放到最终的位置
    }

    public static void print(int[] data) {
        if (data == null) return;
        for (int i = 0; i < data.length; i++) {
            if (i < data.length - 1) {
                System.out.print(String.format("%02d", data[i]) + " ");
            } else {
                System.out.println(String.format("%02d", data[i]));
            }
        }
    }

    public static int[] genData(int size) {
        int[] data = new int[size];
        for (int i = 0; i < size; i++) {
            data[i] = (int) (Math.random() * 100);
        }
        return data;
    }

    public static void swap(int[] data, int x, int y) {
        int length = data.length;
        if (x < 0 || y < 0 || x > length - 1 || y > length - 1)
            throw new IllegalArgumentException();

        int temp = data[x];
        data[x] = data[y];
        data[y] = temp;
    }

}
